#include <iostream>
#include <memory>
#include <fstream>
#include <mutex>
#include <vector>
#include <thread>
#include <cstring>

class FileHandler
{
private:
    std::ofstream file;

public:
    FileHandler(const std::string &filename) : file(filename)
    {
        if (!file.is_open())
        {
            throw std::runtime_error("Failed to open the file");
        }
        std::cout << "File opened successfully1" << std::endl;
    }

    void write(const std::string &data)
    {
        file << data << std::endl;
        std::cout << "Data written to the file" << data << std::endl;
    }

    ~FileHandler()
    {
        if (file.is_open())
        {
            // 读取文件内容并输出
            file.close();
            std::cout << "File closed successfully" << std::endl;
        }
    }
};

void processFile()
{
    FileHandler handler("example.txt");

    handler.write("Hello, RAII!");
    handler.write("Automatic resource management");
}

void exceptionSafeExample()
{
    try
    {
        FileHandler handler("example.txt");
        handler.write("Hello, RAII2!");
        handler.write("Automatic resource management2");
        throw std::runtime_error("An exception occurred");
        handler.write("This line won't be executed");
    }
    catch (const std::exception &e)
    {
        std::cout << "Exception caught1" << std::endl;
        std::cout << "Exception caught2" << e.what() << std::endl;
        std::cerr << "Exception:" << e.what() << std::endl;
        std::cerr.flush();
    }
}

class Resource
{
public:
    Resource()
    {
        std::cout << "Resource acquired" << std::endl;
    }

    ~Resource()
    {
        std::cout << "Resource released" << std::endl;
    }

    void doSomething()
    {
        std::cout << "Doing something with the resource" << std::endl;
    }
};

void uniquePtrExample()
{
    std::unique_ptr<Resource> res = std::make_unique<Resource>();
    res->doSomething();
    res.reset();

    std::cout << "Unique ptr example finished" << std::endl;

    res = std::make_unique<Resource>();
    res->doSomething();
}

void sharedPtrExample()
{
    std::shared_ptr<Resource> res1 = std::make_shared<Resource>();
    {
        std::shared_ptr<Resource> res2 = res1;
        std::shared_ptr<Resource> res3 = res1;
        res1->doSomething();
    }
    res1->doSomething();
    std::cout << "Shared ptr example finished" << std::endl;
}

class Node
{
public:
    std::string name;
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev; // 弱引用,防止循环引用

    Node(const std::string &name) : name(name)
    {
        std::cout << "Node created:" << name << std::endl;
    }
    ~Node()
    {
        std::cout << "Node destroyed:" << name << std::endl;
    }
};

void circularLinkedListExample()
{
    auto node1 = std::make_shared<Node>("Node1");
    auto node2 = std::make_shared<Node>("Node2");
    node1->next = node2;
    node2->prev = node1;
    if (auto preNode = node2->prev.lock())
    {
        std::cout << "Previous node of Node2:" << preNode->name << std::endl;
    }
}

class ScopedLOck
{
private:
    std::mutex &mutex;

public:
    ScopedLOck(std::mutex &m) : mutex(m)
    {
        mutex.lock();
        std::cout << "Lock acquired" << std::endl;
    }

    ~ScopedLOck()
    {
        mutex.unlock();
        std::cout << "Lock released" << std::endl;
    }

    // 禁止拷贝
    ScopedLOck(const ScopedLOck &) = delete;
    ScopedLOck &operator=(const ScopedLOck &) = delete;
};

void cirticalSection(std::mutex &mutex)
{
    ScopedLOck lock(mutex);

    std::cout << "Cirtical section" << std::endl;
    // 可能抛出异常的代码
    //    if(rand()%2==0){
    //     std::cout<<"Exception in cirtical section"<<std::endl;
    //     throw std::runtime_error("Exception in cirtical section");
    //    }
    // std::cout << "Exception in cirtical section" << std::endl;
    // throw std::runtime_error("Exception in cirtical section");
}

class Buffer
{
private:
    std::unique_ptr<int[]> data;
    size_t size;

public:
    explicit Buffer(size_t s) : size(s), data(std::make_unique<int[]>(s))
    {
        std::cout << "Buffer created,size=" << size << std::endl;
        // 初始化缓冲区为0
        std::memset(data.get(), 0, size);
    }

    // 移动复制运算符
    
    Buffer(Buffer &&other) noexcept : size(other.size), data(std::move(other.data))
    {
        other.size = 0;
        std::cout << "Buffer moved" << std::endl;
    }

    ~Buffer()
    {
        std::cout << "Buffer destroyed" << std::endl;
    }
    // 禁止复制
    Buffer(const Buffer &) = delete;
    Buffer &operator=(const Buffer &) = delete;

    // 移动赋值运算符
    Buffer &operator=(Buffer &&other) noexcept
    {
        if (this != &other)
        {
            size = other.size;
            data = std::move(other.data);
            other.size = 0;
            std::cout << "Buffer moved" << std::endl;
        }
        return *this;
    }

    // 写入数据
    void write(const char *data, size_t offset, size_t length)
    {
        if (!data || offset + length > size)
        {
            throw std::runtime_error("Invalid data or offset");
        }
        std::memcpy(this->data.get() + offset, data, length);
        std::cout << "Data written to buffer" << std::endl;
    }

    // 读取数据
    void read(char *data, size_t offset, size_t length) const
    {
        if (!data || offset + length > size)
        {
            throw std::runtime_error("Invalid data or offset");
        }
        std::memcpy(data, this->data.get() + offset, length);
        std::cout << "Data read from buffer" << std::endl;
    }
    // 重置缓冲区
    void reset()
    {
        if (data)
        {
            std::memset(data.get(), 0, size);
            std::cout << "Buffer reset" << std::endl;
        }
    }

    // 获取大小
    size_t getSize() const
    {
        return size;
    }

    // 检查是否有效
    bool isValid() const
    {
        return data != nullptr && size > 0;
    }

    // 交换两个缓冲区
    friend void swap(Buffer &first, Buffer &second) noexcept
    {
        std::swap(first.data, second.data);
        std::swap(first.size, second.size);
        std::cout << "Buffers swapped" << std::endl;
    }
};

// 工厂函数，利用移动语义高效创建buffer
Buffer createBuffer(size_t size)
{
    Buffer buffer(size);
    return buffer;
}


// 处理Buffer的函数，接收移动进来的buffer
void processBuffer(Buffer&& buffer)
{
   std::cout<<"Buffer size:"<<buffer.getSize()<<std::endl;
   if(buffer.isValid()){
      const char* data="Hello,Buffer";
      buffer.write(data,0,std::strlen(data));
      char readData[100]={0};
      buffer.read(readData,0,std::strlen(data));
      std::cout<<"Read data:"<<readData<<std::endl;
   } 
}

void bufferExample()
{
     std::cout<<"Buffer example"<<std::endl;
     // 创建一个Buffer对象
     Buffer buffer1(100);
     // 写入一些数据
     const char* data="Hello,Buffer";
     buffer1.write(data,0,std::strlen(data));

     //使用移动构造函数
     Buffer buffer2(std::move(buffer1));

     //此时buffer1 已被移动,但仍处于有效状态
     std::cout<<"Buffer1 size:"<<buffer1.getSize()<<",valid"<<(buffer1.isValid()?"Yes":"no")<<std::endl;
     std::cout<<"Buffer2 size:"<<buffer2.getSize()<<",valid"<<(buffer2.isValid()?"Yes":"no")<<std::endl;

     // 使用工厂函数
     std::cout<<"Factory function"<<std::endl;
     Buffer buffer3=createBuffer(200);

     // 使用移动赋值运算符
     std::cout<<"Move assignment operator"<<std::endl;
     buffer3=std::move(buffer2);


     // buffer2被移动,buffer3包含buffer2的数据
     std::cout<<"Buffer2 size:"<<buffer2.getSize()<<",valid"<<(buffer2.isValid()?"Yes":"no")<<std::endl;
     std::cout<<"Buffer3 size:"<<buffer3.getSize()<<",valid"<<(buffer3.isValid()?"Yes":"no")<<std::endl;

     //从buffer3读取数据
     char readData[100]={0};
     buffer3.read(readData,0,std::strlen(data));
     std::cout<<"Read data:"<<readData<<std::endl;

     //创建另一个buffer并调用处理函数
     std::cout<<"Process buffer"<<std::endl;
     processBuffer(std::move(buffer3));

     //buffer3已被移动,但仍处于有效状态
     std::cout<<"Buffer3 size:"<<buffer3.getSize()<<",valid"<<(buffer3.isValid()?"Yes":"no")<<std::endl;

     //创建2个buffer以演示交换
     std::cout<<"Swap buffers"<<std::endl;
     Buffer buffer4(50);
     buffer4.write("Buffer4",0,std::strlen(data));
     Buffer buffer5(100);
     buffer5.write("Buffer5",0,std::strlen(data));
     std::cout<<"Buffer4 size:"<<buffer4.getSize()<<",valid"<<(buffer4.isValid()?"Yes":"no")<<std::endl;
     std::cout<<"Buffer5 size:"<<buffer5.getSize()<<",valid"<<(buffer5.isValid()?"Yes":"no")<<std::endl;
     swap(buffer4,buffer5);
     std::cout<<"Buffer4 size:"<<buffer4.getSize()<<",valid"<<(buffer4.isValid()?"Yes":"no")<<std::endl;
     std::cout<<"Buffer5 size:"<<buffer5.getSize()<<",valid"<<(buffer5.isValid()?"Yes":"no")<<std::endl;

     std::cout<<"Buffer example finished"<<std::endl;
}


int main()
{
    processFile();
    exceptionSafeExample();
    uniquePtrExample();
    circularLinkedListExample();
    std::mutex mutex;
    cirticalSection(mutex);
    bufferExample();
    return 0;
}